diff --git a/src/components/containers/FullWidth/index.tsx b/src/components/containers/FullWidth/index.tsx index f2f8a603..3c3eefed 100644 --- a/src/components/containers/FullWidth/index.tsx +++ b/src/components/containers/FullWidth/index.tsx @@ -2,7 +2,11 @@ import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 're import styles from './styles.module.scss'; import ResizeSensor from 'resize-sensor'; -const FullWidth: FC = ({ children }) => { +interface IProps { + onRefresh?: (width: number) => void; +} + +const FullWidth: FC = ({ children, onRefresh }) => { const sample = useRef(null); const [clientWidth, setClientWidth] = useState(document.documentElement.clientWidth); @@ -12,11 +16,13 @@ const FullWidth: FC = ({ children }) => { const { width } = sample.current.getBoundingClientRect(); const { clientWidth } = document.documentElement; + onRefresh(clientWidth); + return { width: clientWidth, transform: `translate(-${(clientWidth - width) / 2}px, 0)`, }; - }, [sample.current, clientWidth]); + }, [sample.current, clientWidth, onRefresh]); const onResize = useCallback(() => setClientWidth(document.documentElement.clientWidth), []); diff --git a/src/components/containers/FullWidth/styles.module.scss b/src/components/containers/FullWidth/styles.module.scss index c1541aec..f318d3c4 100644 --- a/src/components/containers/FullWidth/styles.module.scss +++ b/src/components/containers/FullWidth/styles.module.scss @@ -6,5 +6,5 @@ } .slider { - max-height: calc(100vh - 125px); + display: block; } diff --git a/src/components/node/NodeImageSlideBlock/index.tsx b/src/components/node/NodeImageSlideBlock/index.tsx index 3f67b153..27f7b42f 100644 --- a/src/components/node/NodeImageSlideBlock/index.tsx +++ b/src/components/node/NodeImageSlideBlock/index.tsx @@ -8,6 +8,7 @@ import { PRESETS } from '~/constants/urls'; import { LoaderCircle } from '~/components/input/LoaderCircle'; import { throttle } from 'throttle-debounce'; import { Icon } from '~/components/input/Icon'; +import { useArrows } from '~/utils/hooks/keys'; interface IProps extends INodeComponentProps {} @@ -239,29 +240,7 @@ const NodeImageSlideBlock: FC = ({ images, ]); - const onKeyDown = useCallback( - event => { - if ( - (event.target.tagName && ['TEXTAREA', 'INPUT'].includes(event.target.tagName)) || - is_modal_shown - ) - return; - - switch (event.key) { - case 'ArrowLeft': - return onPrev(); - case 'ArrowRight': - return onNext(); - } - }, - [onNext, onPrev, is_modal_shown] - ); - - useEffect(() => { - window.addEventListener('keydown', onKeyDown); - - return () => window.removeEventListener('keydown', onKeyDown); - }, [onKeyDown]); + useArrows(onNext, onPrev, is_modal_shown); useEffect(() => { setOffset(0); diff --git a/src/components/node/NodeImageTinySlider/index.tsx b/src/components/node/NodeImageTinySlider/index.tsx index 8c9ce2e3..a84d9b50 100644 --- a/src/components/node/NodeImageTinySlider/index.tsx +++ b/src/components/node/NodeImageTinySlider/index.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import { INodeComponentProps } from '~/redux/node/constants'; import { FullWidth } from '~/components/containers/FullWidth'; import { useNodeImages } from '~/utils/node'; @@ -6,7 +6,8 @@ import { getURL } from '~/utils/dom'; import { PRESETS } from '~/constants/urls'; import TinySlider from 'tiny-slider-react'; import styles from './styles.module.scss'; -import { TinySliderSettings } from 'tiny-slider'; +import { TinySliderInstance, TinySliderSettings } from 'tiny-slider'; +import { useArrows } from '~/utils/hooks/keys'; const settings: TinySliderSettings & { center: boolean } = { nav: false, @@ -20,19 +21,67 @@ const settings: TinySliderSettings & { center: boolean } = { arrowKeys: false, // prevButton: false, // nextButton: false, + autoHeight: true, swipeAngle: 45, + responsive: { + 0: { + edgePadding: 10, + gutter: 40, + }, + 768: { + edgePadding: 50, + }, + 1024: { + edgePadding: 150, + }, + }, }; const NodeImageTinySlider: FC = ({ node }) => { + const ref = useRef(null); + const slides = useRef([]); const images = useNodeImages(node); + const [current, setCurrent] = useState(0); + const [height, setHeight] = useState(images[0]?.metadata?.height || 0); + + const onResize = useCallback(() => { + if (!ref.current) return; + ref.current.slider.refresh(); + const el = slides.current[current]; + if (!el) return; + const { height } = el.getBoundingClientRect(); + setHeight(height); + }, [ref.current, slides.current, current]); + + const onIndexChanged = useCallback(({ index }) => { + setCurrent(index || 0); + }, []); + + useEffect(() => { + setCurrent(0); + }, [node.id]); + + useEffect(onResize, [slides, current]); + + const onNext = useCallback(() => { + if (!ref.current || images.length <= 1 || current === images.length - 1) return; + ref.current.slider.goTo(current + 1); + }, [ref.current, current, images]); + + const onPrev = useCallback(() => { + if (!ref.current || images.length <= 1 || current === 0) return; + ref.current.slider.goTo(current - 1); + }, [ref.current, current, images]); + + useArrows(onNext, onPrev, false); return ( - -
- - {images.map(image => ( -
- + +
+ + {images.map((image, i) => ( +
(slides.current[i] = el)}> +
))}
diff --git a/src/components/node/NodeImageTinySlider/styles.module.scss b/src/components/node/NodeImageTinySlider/styles.module.scss index 980681f2..ec978ab3 100644 --- a/src/components/node/NodeImageTinySlider/styles.module.scss +++ b/src/components/node/NodeImageTinySlider/styles.module.scss @@ -1,5 +1,7 @@ .slider { padding-bottom: 15px; + overflow: hidden; + transition: height 0.25s; :global(.tns-controls) { display: none; @@ -8,12 +10,12 @@ .slide { align-items: center; - display: flex; + display: inline-flex; justify-content: center; text-align: center; img { - max-height: calc(100vh - 150px); + max-height: calc(100vh - 140px); max-width: 100%; border-radius: $radius; } diff --git a/src/utils/hooks.ts b/src/utils/hooks/index.ts similarity index 100% rename from src/utils/hooks.ts rename to src/utils/hooks/index.ts diff --git a/src/utils/hooks/keys.ts b/src/utils/hooks/keys.ts new file mode 100644 index 00000000..93432d00 --- /dev/null +++ b/src/utils/hooks/keys.ts @@ -0,0 +1,23 @@ +import { useCallback, useEffect } from 'react'; + +export const useArrows = (onNext: () => void, onPrev: () => void, locked) => { + const onKeyDown = useCallback( + event => { + if ((event.target.tagName && ['TEXTAREA', 'INPUT'].includes(event.target.tagName)) || locked) + return; + + switch (event.key) { + case 'ArrowLeft': + return onPrev(); + case 'ArrowRight': + return onNext(); + } + }, + [onNext, onPrev, locked] + ); + + useEffect(() => { + window.addEventListener('keydown', onKeyDown); + return () => window.removeEventListener('keydown', onKeyDown); + }, [onKeyDown]); +};