import React, {useRef, useEffect, useState} from 'react' export default ({images = [], className, onChange, onClick, ...props}) => { const divRef = useRef() const containerRef = useRef() const autoscroll = useRef(false) const inTouch = useRef(false) const timeout = useRef(false) const [imgs, setImgs] = useState([]) const [current, setCurrent] = useState(0) const currentScrollPosition = useRef(0) useEffect(() => { if (divRef.current){ const div = divRef.current const totalWidth = imgs.reduce((total, img) => total + (img?.getBoundingClientRect().width || 0),0) div.style.minWidth = totalWidth + 'px' } }, [divRef, imgs]) const scrollToCurrent = () => { const el = containerRef.current autoscroll.current = true const step = () => { if (!autoscroll.current || !el) return; const {scrollLeft} = el const diff = (currentScrollPosition.current - scrollLeft) /5 if (Math.abs(diff) > 1){ el.scrollTo(scrollLeft + diff, 0) setTimeout(step, 20) } else { el.scrollTo(currentScrollPosition.current, 0) autoscroll.current = false } } step() //if (milaCount !== current +1) set(current +1) } const onTouchEnd = () => { if (inTouch.current){ if (timeout.current) clearInterval(timeout.current) timeout.current = setTimeout(onTouchEnd, 200) return; } const {scrollLeft, scrollWidth} = containerRef.current; const viewPortWidth = containerRef.current.getBoundingClientRect().width let newCurrent; if (scrollLeft === 0) { newCurrent = 0 currentScrollPosition.current = 0 } else if (scrollLeft >= scrollWidth - viewPortWidth) { newCurrent = (images.length -1) currentScrollPosition.current = scrollWidth - viewPortWidth } else { let imgsWidth = 0 let i = 0 for (const img of imgs){ const imgWidth = img?.getBoundingClientRect().width || 0 imgsWidth += imgWidth if (imgsWidth > scrollLeft){ break; } i++ } const offset = imgsWidth - scrollLeft newCurrent = i currentScrollPosition.current = imgsWidth - (imgs?.[i].getBoundingClientRect().width || 0) if (offset < viewPortWidth/2){ currentScrollPosition.current = imgsWidth newCurrent++ } } setCurrent(newCurrent) if (newCurrent === current) scrollToCurrent() else if (typeof onChange === 'function') onChange(newCurrent) } const onScroll = e => { //autoscroll.current = false if (autoscroll.current) return; if (timeout.current) clearInterval(timeout.current) timeout.current = setTimeout(onTouchEnd, 200) } useEffect(scrollToCurrent, [current]) const isTouchDevice = () => (navigator.maxTouchPoints || 'ontouchstart' in document.documentElement); const onImgClick = (e, i) => { const touchDevice = isTouchDevice() if (touchDevice && typeof onClick === 'function'){ onClick(i) } else { const viewPortWidth = containerRef.current.getBoundingClientRect().width const clickX = e.clientX -e.target.getBoundingClientRect().x const {scrollLeft} = containerRef.current; if (clickX > viewPortWidth * 0.75) { if (i < images.length -1){ currentScrollPosition.current = scrollLeft + (imgs?.[i].getBoundingClientRect().width || 0) setCurrent(i +1) scrollToCurrent() if (typeof onChange === 'function') onChange(i +1) } } else if (clickX < viewPortWidth * 0.25) { if (i > 0){ currentScrollPosition.current = scrollLeft - (imgs?.[i-1].getBoundingClientRect().width || 0) setCurrent(i -1) scrollToCurrent() if (typeof onChange === 'function') onChange(i -1) } } else if (typeof onClick === 'function'){ onClick(i) } } } return (