@chayns-components/gallery
Version:
A set of beautiful React components for developing your own applications with chayns.
319 lines (307 loc) • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _core = require("@chayns-components/core");
var _chaynsApi = require("chayns-api");
var _react = _interopRequireWildcard(require("react"));
var _uuid = require("uuid");
var _gallery = require("../types/gallery");
var _file = require("../utils/file");
var _AddFile = _interopRequireDefault(require("./add-file/AddFile"));
var _GalleryItem = _interopRequireDefault(require("./gallery-item/GalleryItem"));
var _Gallery = require("./Gallery.styles");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const Gallery = ({
allowDragAndDrop = false,
doubleFileDialogMessage = 'Diese Datei ist bereits vorhanden',
isEditMode = false,
fileMinWidth = 100,
files,
maxFiles,
onAdd,
onFileCountChange,
onRemove,
viewMode = _gallery.GalleryViewMode.GRID
}) => {
const [fileItems, setFileItems] = (0, _react.useState)([]);
/**
* This function adds a previewUrl to fileItems
*/
const handlePreviewUrlCallback = (previewUrl, file) => {
setFileItems(prevState => prevState.map(prevFile => {
if (prevFile.id === file.id) {
return {
...prevFile,
previewUrl
};
}
return prevFile;
}));
};
const callDuplicateFileDialog = (0, _react.useCallback)(() => {
(0, _chaynsApi.createDialog)({
type: _chaynsApi.DialogType.ALERT,
text: doubleFileDialogMessage
});
}, [doubleFileDialogMessage]);
/**
* This function adds uploaded files to fileItems
*/
const handleUploadFileCallback = (0, _react.useCallback)((file, uploadedFile) => {
setFileItems(prevState => {
const updatedState = prevState.map(prevFile => {
var _prevFile$uploadedFil;
if (((_prevFile$uploadedFil = prevFile.uploadedFile) === null || _prevFile$uploadedFil === void 0 ? void 0 : _prevFile$uploadedFil.url) === uploadedFile.url) {
callDuplicateFileDialog();
return undefined;
}
if (prevFile.id === file.id) {
if (typeof onAdd === 'function') {
const prevElement = prevState.find(({
uploadedFile: newUploadedFile
}) => (newUploadedFile === null || newUploadedFile === void 0 ? void 0 : newUploadedFile.url) === (uploadedFile === null || uploadedFile === void 0 ? void 0 : uploadedFile.url));
if (!prevElement) {
onAdd({
file: uploadedFile,
id: file.id
});
}
}
return {
...prevFile,
uploadedFile,
state: 'uploaded'
};
}
return prevFile;
});
const tmp = [];
updatedState.forEach(updatedFile => {
if (updatedFile !== undefined) {
tmp.push(updatedFile);
}
});
return tmp ?? [];
});
}, [callDuplicateFileDialog, onAdd]);
/**
* Returns the current count to check if all files are uploaded
*/
(0, _react.useEffect)(() => {
if (typeof onFileCountChange === 'function') {
onFileCountChange(fileItems.length);
}
}, [fileItems.length, onFileCountChange]);
/**
* Prepares files for previewUrl and upload
*/
(0, _react.useEffect)(() => {
const filesToGeneratePreview = fileItems.filter(file => file.file && !file.previewUrl && (file.state === 'none' || !file.state));
const filesToUpload = fileItems.filter(file => !file.uploadedFile && file.state !== 'uploading');
filesToGeneratePreview.forEach(file => {
if (!file.file) {
return;
}
if (file.file.type.includes('video/')) {
(0, _file.generateVideoThumbnail)({
file: file.file,
callback: previewUrl => handlePreviewUrlCallback(previewUrl, file)
});
return;
}
(0, _file.generatePreviewUrl)({
file: file.file,
callback: previewUrl => handlePreviewUrlCallback(previewUrl, file)
});
});
filesToUpload.forEach(file => {
setFileItems(prevState => prevState.map(prevFile => {
if (prevFile.id === file.id) {
return {
...prevFile,
state: 'uploading'
};
}
return prevFile;
}));
void (0, _core.uploadFile)({
fileToUpload: file,
callback: UploadedFile => handleUploadFileCallback(file, UploadedFile)
});
});
}, [fileItems, handleUploadFileCallback]);
/**
* This function formats and adds files to fileItems
*/
const handleAddFiles = (0, _react.useCallback)(filesToAdd => {
const newFileItems = [];
filesToAdd.forEach(file => {
if (file && !(0, _file.filterDuplicateFile)({
files: fileItems,
newFile: file
})) {
newFileItems.push({
id: (0, _uuid.v4)(),
file,
state: 'none'
});
}
});
let tmp = newFileItems;
if (maxFiles) {
tmp = newFileItems.slice(0, maxFiles - (fileItems.length + filesToAdd.length - 1));
}
setFileItems(prevState => [...prevState, ...tmp]);
}, [fileItems, maxFiles]);
/**
* This function adds external files to fileItems
*/
(0, _react.useEffect)(() => {
if (files) {
const newFileItems = [];
files.forEach(file => {
newFileItems.push({
id: file.id ?? (0, _uuid.v4)(),
uploadedFile: file.file,
file: undefined,
state: 'uploaded',
previewUrl: undefined
});
});
setFileItems(prevState => {
const updatedItems = prevState.map(prevItem => {
const newItem = newFileItems.find(item => item.uploadedFile && item.uploadedFile.url === (prevItem.uploadedFile && prevItem.uploadedFile.url));
return newItem || prevItem;
});
return updatedItems.concat(newFileItems.filter(newItem => !prevState.some(prevItem => prevItem.uploadedFile && newItem.uploadedFile && prevItem.uploadedFile.url === newItem.uploadedFile.url)));
});
}
}, [files]);
/**
* This function deletes a selected file from the file list
*/
const handleDeleteFile = (0, _react.useCallback)(id => {
let fileToDelete;
const filteredFiles = fileItems.filter(file => {
const fileId = file.id;
if (fileId === id && file.uploadedFile) {
fileToDelete = {
file: file.uploadedFile,
id
};
}
return fileId !== id;
});
setFileItems(filteredFiles);
if (!fileToDelete || typeof onRemove !== 'function') {
return;
}
onRemove(fileToDelete);
}, [fileItems, onRemove]);
/**
* This function handles the drag and drop
*/
const handleDrop = (0, _react.useCallback)(e => {
if (!allowDragAndDrop) {
return;
}
e.preventDefault();
const draggedFiles = Array.from(e.dataTransfer.files);
handleAddFiles(draggedFiles);
}, [allowDragAndDrop, handleAddFiles]);
/**
* Opens the files in a slideShow
*/
const openFiles = (0, _react.useCallback)(file => {
const startIndex = fileItems.findIndex(item => item.id === file.id);
const items = fileItems.map(item => {
var _item$uploadedFile;
return {
url: ((_item$uploadedFile = item.uploadedFile) === null || _item$uploadedFile === void 0 ? void 0 : _item$uploadedFile.url.replace('_0.mp4', '.mp4')) ?? '',
mediaType: item.uploadedFile && 'thumbnailUrl' in item.uploadedFile ? _chaynsApi.MediaType.VIDEO : _chaynsApi.MediaType.IMAGE
};
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
void (0, _chaynsApi.openMedia)({
items,
startIndex
});
}, [fileItems]);
/**
* Returns the ratio of the single file
*/
const ratio = (0, _react.useMemo)(() => {
var _fileItems$;
switch (fileItems.length) {
case 0:
return 0;
case 1:
return Math.max(((_fileItems$ = fileItems[0]) === null || _fileItems$ === void 0 || (_fileItems$ = _fileItems$.uploadedFile) === null || _fileItems$ === void 0 ? void 0 : _fileItems$.ratio) ?? 1, 1);
case 2:
return 2;
case 3:
return 3;
default:
return 1;
}
}, [fileItems]);
const galleryContent = (0, _react.useMemo)(() => {
const combinedFilesLength = fileItems.length;
if (isEditMode) {
const items = fileItems.map(file => /*#__PURE__*/_react.default.createElement(_GalleryItem.default, {
key: file.id,
fileItem: file,
isEditMode: true,
onClick: openFiles,
handleDeleteFile: handleDeleteFile
}));
if (maxFiles && maxFiles <= combinedFilesLength) {
return items;
}
items.push(/*#__PURE__*/_react.default.createElement(_AddFile.default, {
key: "add_file",
onAdd: handleAddFiles
}));
return items;
}
const shortedFiles = fileItems.slice(0, 4);
return shortedFiles.map((file, index) => {
let imageRatio = 1;
if (viewMode === _gallery.GalleryViewMode.GRID) {
if (combinedFilesLength === 1) {
var _fileItems$2;
imageRatio = ((_fileItems$2 = fileItems[0]) === null || _fileItems$2 === void 0 || (_fileItems$2 = _fileItems$2.uploadedFile) === null || _fileItems$2 === void 0 ? void 0 : _fileItems$2.ratio) ?? 1;
} else if (combinedFilesLength === 2 && (index === 0 || index === 1)) {
imageRatio = 0.5;
} else if (index === 0 && combinedFilesLength > 2 || combinedFilesLength === 3 && (index === 1 || index === 2)) {
imageRatio = 1.5;
}
}
return /*#__PURE__*/_react.default.createElement(_GalleryItem.default, {
key: file.id,
fileItem: file,
isEditMode: false,
handleDeleteFile: handleDeleteFile,
onClick: openFiles,
ratio: imageRatio,
remainingItemsLength: combinedFilesLength > 4 && index === 3 ? combinedFilesLength : undefined
});
});
}, [fileItems, isEditMode, maxFiles, handleAddFiles, openFiles, handleDeleteFile, viewMode]);
return (0, _react.useMemo)(() => /*#__PURE__*/_react.default.createElement(_Gallery.StyledGallery, null, isEditMode ? /*#__PURE__*/_react.default.createElement(_Gallery.StyledGalleryEditModeWrapper, {
$fileMinWidth: fileMinWidth,
onDragOver: e => e.preventDefault(),
onDrop: e => void handleDrop(e)
}, galleryContent) : /*#__PURE__*/_react.default.createElement(_Gallery.StyledGalleryItemWrapper, {
$ratio: ratio,
$uploadedFileLength: fileItems.length,
$viewMode: viewMode
}, galleryContent)), [isEditMode, fileMinWidth, galleryContent, ratio, fileItems.length, viewMode, handleDrop]);
};
Gallery.displayName = 'Gallery';
var _default = exports.default = Gallery;
//# sourceMappingURL=Gallery.js.map