diff --git a/package.json b/package.json index 133af634..ca720cff 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "mobx-persist-store": "^1.0.4", "mobx-react-lite": "^3.2.3", "next": "^12.3.0", - "photoswipe": "^4.1.3", + "photoswipe": "^5.4.4", "raleway-cyrillic": "^4.0.2", "ramda": "^0.26.1", "react": "^17.0.2", @@ -41,7 +41,7 @@ "react-sticky-box": "^1.0.2", "sass": "^1.49.0", "sharp": "^0.32.6", - "swiper": "^11.0.3", + "swiper": "^11.2.2", "swr": "^1.0.1", "throttle-debounce": "^2.1.0", "typescript": "^4.0.5", diff --git a/src/components/common/Columns/index.tsx b/src/components/common/Columns/index.tsx index 6901c609..e491e77c 100644 --- a/src/components/common/Columns/index.tsx +++ b/src/components/common/Columns/index.tsx @@ -31,7 +31,7 @@ const Columns: FC = ({ if (!childs) return; - const timeout = setTimeout(() => setColumns([...childs]), 150); + const timeout = setTimeout(() => setColumns([...childs.values()]), 150); return () => clearTimeout(timeout); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/components/node/NodeImageSwiperBlock/index.tsx b/src/components/node/NodeImageSwiperBlock/index.tsx index 9e5d8082..c3c778d3 100644 --- a/src/components/node/NodeImageSwiperBlock/index.tsx +++ b/src/components/node/NodeImageSwiperBlock/index.tsx @@ -57,7 +57,9 @@ const NodeImageSwiperBlock: FC = observer(({ node }) => { useEffect(() => { controlledSwiper?.slideTo(0, 0); - return () => controlledSwiper?.slideTo(0, 0); + return () => { + controlledSwiper?.slideTo(0, 0); + }; }, [controlledSwiper, images, node.id]); useEffect(() => { diff --git a/src/containers/dialogs/PhotoSwipe/index.tsx b/src/containers/dialogs/PhotoSwipe/index.tsx index 3a285696..b5baccb7 100644 --- a/src/containers/dialogs/PhotoSwipe/index.tsx +++ b/src/containers/dialogs/PhotoSwipe/index.tsx @@ -1,10 +1,12 @@ -import { useEffect, useRef, VFC } from 'react'; +import { useEffect } from 'react'; + +import 'photoswipe/style.css'; -import classNames from 'classnames'; import { observer } from 'mobx-react-lite'; -import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default.js'; -import PhotoSwipeJs from 'photoswipe/dist/photoswipe.js'; +import { SlideData } from 'photoswipe/dist/types/slide/slide'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { Icon } from '~/components/common/Icon'; import { imagePresets } from '~/constants/urls'; import { useWindowSize } from '~/hooks/dom/useWindowSize'; import { useModal } from '~/hooks/modal/useModal'; @@ -13,125 +15,83 @@ import { DialogComponentProps } from '~/types/modal'; import { getURL } from '~/utils/dom'; import styles from './styles.module.scss'; - -export interface PhotoSwipeProps extends DialogComponentProps { +export interface Props extends DialogComponentProps { items: IFile[]; index: number; } -const PhotoSwipe: VFC = observer(({ index, items }) => { - let ref = useRef(null); +const arrowNextSVG = renderToStaticMarkup(); +const arrowPrevSVG = renderToStaticMarkup(); +const closeSVG = renderToStaticMarkup(); + +const padding = { top: 10, left: 10, right: 10, bottom: 10 } as const; + +const PhotoSwipe = observer(({ index, items }: Props) => { const { hideModal } = useModal(); const { isTablet } = useWindowSize(); useEffect(() => { - new Promise(async (resolve) => { - const images = await Promise.all( - items.map( - (file) => - new Promise((resolve) => { - const src = getURL( - file, - isTablet ? imagePresets[900] : imagePresets[1600], - ); + Promise.all( + items.map( + (file): Promise => + new Promise((resolve) => { + const src = getURL( + file, + isTablet ? imagePresets[900] : imagePresets[1600], + ); - if (file.metadata?.width && file.metadata.height) { - resolve({ - src, - w: file.metadata.width, - h: file.metadata.height, - }); + if (file.metadata?.width && file.metadata.height) { + resolve({ + src, + width: file.metadata.width, + height: file.metadata.height, + }); - return; - } + return; + } - const img = new Image(); + const img = new Image(); - img.onload = () => { - resolve({ - src, - h: img.naturalHeight, - w: img.naturalWidth, - }); - }; + img.onload = () => { + resolve({ + src, + height: img.naturalHeight, + width: img.naturalWidth, + }); + }; - img.onerror = () => { - resolve({}); - }; + img.onerror = () => { + resolve({}); + }; - img.src = getURL(file, imagePresets[1600]); - }), - ), - ); + img.src = getURL(file, imagePresets[1600]); + }), + ), + ).then(async (images: SlideData[]) => { + const PSWP = await import('photoswipe').then((it) => it.default); - resolve(images); - }).then((images) => { - const ps = new PhotoSwipeJs(ref.current, PhotoSwipeUI_Default, images, { + const ps = new PSWP({ + dataSource: images, index: index || 0, - closeOnScroll: false, - history: false, + closeOnVerticalDrag: true, + padding, + mainClass: styles.wrap, + zoom: false, + counter: false, + bgOpacity: 0.1, + arrowNextSVG, + arrowPrevSVG, + closeSVG, }); + ps.on('destroy', hideModal); + ps.on('close', hideModal); + ps.init(); - ps.listen('destroy', hideModal); - ps.listen('close', hideModal); }); }, [hideModal, items, index, isTablet]); - return ( -