@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
139 lines (138 loc) • 9.3 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Grid, IconButton, Typography } from '@mui/material';
import Icon from '@mui/material/Icon';
import { styled } from '@mui/material/styles';
import { Link } from '@selfcommunity/react-core';
import classNames from 'classnames';
import { MEDIA_TYPE_DOCUMENT } from '../../../constants/Media';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import { Lightbox } from '../../Lightbox';
import { PREFIX } from './constants';
import filter from './filter';
const classes = {
displayRoot: `${PREFIX}-display-root`,
background: `${PREFIX}-background`,
backgroundPortrait: `${PREFIX}-background-portrait`,
heightOne: `${PREFIX}-height-one`,
heightHalfOne: `${PREFIX}-height-half-one`,
heightTwo: `${PREFIX}-height-two`,
heightThree: `${PREFIX}-height-three`,
cover: `${PREFIX}-cover`,
coverText: `${PREFIX}-cover-text`,
slide: `${PREFIX}-slide`,
border: `${PREFIX}-border`,
gallery: `${PREFIX}-gallery`,
title: `${PREFIX}-title`,
iconFile: `${PREFIX}-icon-file`
};
const Root = styled(Box, {
name: PREFIX,
slot: 'DisplayRoot'
})(({}) => ({}));
export default (props) => {
// PROPS
const { className = '', medias = [], maxVisible = 5, gallery = true, onMediaClick = null } = props;
// STATE
const [preview, setPreview] = useState(-1);
const [toolbarButtons, setToolbarButtons] = useState(undefined);
const { ref, inView } = useInView({ triggerOnce: false });
// MEMO
const _medias = useMemo(() => medias.filter(filter), [medias]);
// HANDLERS
const handleClose = () => {
setPreview(-1);
setToolbarButtons(undefined);
};
// UTILS
const getImageUrl = (image, original = false) => {
if (typeof image === 'object') {
const _image = image.image_thumbnail ? image.image_thumbnail.url : image.image ? image.image : '/static/frontend_v2/images/image.svg';
return original && image.image ? image.image : _image;
}
return image;
};
const openPreviewImage = useCallback((index) => {
if (gallery === false) {
// Prevent gallery
return;
}
setPreview(index);
onMediaClick(_medias[index]);
}, [_medias]);
// RENDERING
const renderTitle = (o) => {
if (!o) {
return null;
}
let startAdornment = null;
if (o.type) {
switch (o.type) {
case 'doc':
startAdornment = _jsx(Icon, Object.assign({ className: classes.iconFile }, { children: "picture_as_pdf" }));
break;
default:
startAdornment = _jsx(Icon, Object.assign({ className: classes.iconFile }, { children: "insert_drive_file" }));
break;
}
}
return (_jsx(React.Fragment, { children: o.title && (_jsx("div", Object.assign({ className: classes.title }, { children: _jsxs(Typography, Object.assign({ variant: "subtitle2" }, { children: [startAdornment, " ", o.title] })) }))) }));
};
const renderOne = () => {
const overlay = _medias.length > maxVisible && maxVisible == 1 ? renderCountOverlay(true) : renderOverlay(0);
const isGif = _medias[0].image_mimetype ? _medias[0].image_mimetype.includes('image/gif') : false;
const isLandscape = _medias[0].image_height < _medias[0].image_width;
return (_jsx(Grid, Object.assign({ container: true, style: Object.assign({}, (_medias[0].image_thumbnail && _medias[0].image_thumbnail.color ? { backgroundColor: _medias[0].image_thumbnail.color } : {})) }, { children: _jsxs(Grid, Object.assign({ item: true, ref: ref, xs: 12, classes: {
root: classNames(classes.border, classes.heightOne, Object.assign(Object.assign({}, (isGif || isLandscape ? { [classes.background]: true } : { [classes.backgroundPortrait]: true })), { [classes.gallery]: gallery, [classes.heightHalfOne]: _medias.length > 1 }))
}, onClick: () => openPreviewImage(0), style: Object.assign({ background: `url(${getImageUrl(_medias[0], inView && isGif)})` }, (isLandscape ? { paddingTop: `${(100 * _medias[0].image_height) / _medias[0].image_width}%` } : {})) }, { children: [overlay, renderTitle(_medias[0])] })) })));
};
const renderTwo = () => {
const overlay = _medias.length > maxVisible && [2, 3].includes(+maxVisible) ? renderCountOverlay(true) : renderOverlay(1);
const conditionalRender = [3, 4].includes(_medias.length) || (_medias.length > +maxVisible && [3, 4].includes(+maxVisible));
return (_jsxs(Grid, Object.assign({ container: true }, { children: [_jsxs(Grid, Object.assign({ item: true, xs: 6, classes: { root: classNames(classes.border, classes.heightTwo, classes.background, { [classes.gallery]: gallery }) }, onClick: () => openPreviewImage(conditionalRender ? 1 : 0), style: { background: `url(${getImageUrl(conditionalRender ? _medias[1] : _medias[0])})` } }, { children: [renderOverlay(conditionalRender ? 1 : 0), renderTitle(_medias[0])] })), _jsxs(Grid, Object.assign({ item: true, xs: 6, classes: { root: classNames(classes.border, classes.heightTwo, classes.background, { [classes.gallery]: gallery }) }, onClick: () => openPreviewImage(conditionalRender ? 2 : 1), style: { background: `url(${getImageUrl(conditionalRender ? _medias[2] : _medias[1])})` } }, { children: [overlay, renderTitle(_medias[1])] }))] })));
};
const renderThree = () => {
const conditionalRender = _medias.length == 4 || (_medias.length > +maxVisible && +maxVisible == 4);
const overlay = !maxVisible || maxVisible > 5 || (_medias.length > maxVisible && [4, 5].includes(+maxVisible))
? renderCountOverlay(true)
: renderOverlay(conditionalRender ? 3 : 4);
return (_jsxs(Grid, Object.assign({ container: true }, { children: [_jsxs(Grid, Object.assign({ item: true, xs: 4, md: 4, classes: { root: classNames(classes.border, classes.heightThree, classes.background, { [classes.gallery]: gallery }) }, onClick: () => openPreviewImage(conditionalRender ? 1 : 2), style: { background: `url(${getImageUrl(conditionalRender ? _medias[1] : _medias[2])})` } }, { children: [renderOverlay(conditionalRender ? 1 : 2), renderTitle(_medias[1])] })), _jsxs(Grid, Object.assign({ item: true, xs: 4, md: 4, classes: { root: classNames(classes.border, classes.heightThree, classes.background, { [classes.gallery]: gallery }) }, onClick: () => openPreviewImage(conditionalRender ? 2 : 3), style: { background: `url(${getImageUrl(conditionalRender ? _medias[2] : _medias[3])})` } }, { children: [renderOverlay(conditionalRender ? 2 : 3), renderTitle(_medias[2])] })), _jsxs(Grid, Object.assign({ item: true, xs: 4, md: 4, classes: { root: classNames(classes.border, classes.heightThree, classes.background, { [classes.gallery]: gallery }) }, onClick: () => openPreviewImage(conditionalRender ? 3 : 4), style: { background: `url(${getImageUrl(conditionalRender ? _medias[3] : _medias[4])})` } }, { children: [overlay, renderTitle(_medias[3])] }))] })));
};
const renderOverlay = (id) => {
if (!gallery) {
return null;
}
return [
_jsx("div", { className: classNames(classes.cover, classes.slide) }, `cover-${id}`),
_jsx("div", Object.assign({ className: classNames(classes.coverText, classes.slide, 'animate-text'), style: { fontSize: '100%' } }, { children: _jsx(Icon, { children: "zoom_out_map" }) }), `cover-text-${id}`)
];
};
const renderCountOverlay = (more) => {
const extra = _medias.length - (maxVisible && maxVisible > 5 ? 5 : maxVisible);
return [
more && _jsx("div", { className: classes.cover }, "count"),
more && (_jsx("div", Object.assign({ className: classes.coverText, style: { fontSize: '200%' } }, { children: _jsxs("p", { children: ["+", extra] }) }), "count-sub"))
];
};
const handleIndexChange = useCallback((index) => {
if (_medias[index].type === MEDIA_TYPE_DOCUMENT) {
setToolbarButtons(_jsx(IconButton, Object.assign({ component: Link, to: medias[index].url, target: "_blank", color: "inherit" }, { children: _jsx(Icon, { children: "download" }) })));
}
else {
setToolbarButtons(undefined);
}
}, [_medias, setToolbarButtons]);
useEffect(() => {
if (preview !== -1) {
handleIndexChange(preview);
}
}, [preview]);
const imagesToShow = [..._medias];
if (maxVisible && _medias.length > maxVisible) {
imagesToShow.length = maxVisible;
}
if (_medias.length === 0) {
return null;
}
return (_jsxs(Root, Object.assign({ className: classNames(classes.displayRoot, className) }, { children: [[1, 3, 4].includes(imagesToShow.length) && renderOne(), imagesToShow.length >= 2 && imagesToShow.length != 4 && renderTwo(), imagesToShow.length >= 4 && renderThree(), preview !== -1 && (_jsx(Lightbox, { onClose: handleClose, index: preview, medias: _medias, toolbarButtons: toolbarButtons, onIndexChange: handleIndexChange }))] })));
};