mirror of
https://github.com/vercel/commerce.git
synced 2025-03-30 17:05:52 +00:00
* Custom Checkout Progress * Updates to Checkout * Custom Checkout Progress * Adding tabs * Adding Collapse * Adding Collapse * Improving Sidebar Scroll * Modif footer * Changes * More design updates * sidebar cart * More design updates * More design updates * More design updates * More design updates * Types * Types * Design Updates * More changes * More changes * More changes * Changes * Changes * Changes * New tailwind required changes * Sidebar Styling issues with Mobile * Latest changes - Normalizing cart * Styling Fixes * New changes * Changes * latest * Refactor and Renaming some UI Props * Adding Quantity Component * Adding Rating Component * Rating Component * More updates * User Select disabled, plus hidding horizontal scroll bars * Changes * Adding ProductOptions Component and more helpers * Styling updates * Styling updates * Fix for slim tags * Missmatch with RightArrow * Footer updates and some styles * Latest Updates * Latest Updates * Latest Updates * Removing Portal, since it's not needed. We might add it later I'd rather not to. * Removing Portal, since it's not needed. We might add it later I'd rather not to. * Sam backdrop filter * General UI Improvements * General UI Improvements * Search now with Geist Colors * Now with Geist Colors * Changes * Scroll for Mobile on IOs devises * LoadingDots Working (: * Changes * More Changes * Perf changes * More perf changes * Fade to the Nametags in the ProductCard * changes * Search issue ui * Search issue ui * Make sure to only refresh navbar and modals when required * Index revalidate * Fixed image issue * hide album scroll on windows * Fix scrollbar * Changing * Adding 404 with Layout * Removing Toast * Adding Assets * Adding Assets * Progress with LocalProvider * New productTag * Only images for the drop * changes * Empty SWRhooks * Adding Local Provider * Working local * Working view of a LocalProvider * More updates * Changes * Removed react-ticker * default to local if no env available * default to local if no env available * add missing `@` to css import * rewrite search rewrites to multiple pages * allow requests in getStaticProps to execute in parallel * make type import explicit * add a tsconfig.js file * use local provider in tsconfig.js * avoid a circular dependency * Saleor was not in the providers list * avoid circular dependency in bigcommerce * Adding more to the Local Provider (#366) * Adding more data * Adding more data * optimize assets (#370) * Optimize assets (#372) * optimize assets * remove assets * remove assets * cart enabled * Adding saleor * Changes with Webpack * Changes Co-authored-by: Luis Alvarez <luis@vercel.com> Co-authored-by: Tobias Koppers <tobias.koppers@googlemail.com> Co-authored-by: Shu Ding <g@shud.in>
137 lines
3.8 KiB
TypeScript
137 lines
3.8 KiB
TypeScript
import { useKeenSlider } from 'keen-slider/react'
|
|
import React, {
|
|
Children,
|
|
FC,
|
|
isValidElement,
|
|
useState,
|
|
useRef,
|
|
useEffect,
|
|
} from 'react'
|
|
import cn from 'classnames'
|
|
import { a } from '@react-spring/web'
|
|
import s from './ProductSlider.module.css'
|
|
import ProductSliderControl from '../ProductSliderControl'
|
|
|
|
interface ProductSliderProps {
|
|
children: React.ReactNode[]
|
|
className?: string
|
|
}
|
|
|
|
const ProductSlider: React.FC<ProductSliderProps> = ({
|
|
children,
|
|
className = '',
|
|
}) => {
|
|
const [currentSlide, setCurrentSlide] = useState(0)
|
|
const [isMounted, setIsMounted] = useState(false)
|
|
const sliderContainerRef = useRef<HTMLDivElement>(null)
|
|
const thumbsContainerRef = useRef<HTMLDivElement>(null)
|
|
|
|
const [ref, slider] = useKeenSlider<HTMLDivElement>({
|
|
loop: true,
|
|
slidesPerView: 1,
|
|
mounted: () => setIsMounted(true),
|
|
slideChanged(s) {
|
|
const slideNumber = s.details().relativeSlide
|
|
setCurrentSlide(slideNumber)
|
|
|
|
if (thumbsContainerRef.current) {
|
|
const $el = document.getElementById(
|
|
`thumb-${s.details().relativeSlide}`
|
|
)
|
|
if (slideNumber >= 3) {
|
|
thumbsContainerRef.current.scrollLeft = $el!.offsetLeft
|
|
} else {
|
|
thumbsContainerRef.current.scrollLeft = 0
|
|
}
|
|
}
|
|
},
|
|
})
|
|
|
|
// Stop the history navigation gesture on touch devices
|
|
useEffect(() => {
|
|
const preventNavigation = (event: TouchEvent) => {
|
|
// Center point of the touch area
|
|
const touchXPosition = event.touches[0].pageX
|
|
// Size of the touch area
|
|
const touchXRadius = event.touches[0].radiusX || 0
|
|
|
|
// We set a threshold (10px) on both sizes of the screen,
|
|
// if the touch area overlaps with the screen edges
|
|
// it's likely to trigger the navigation. We prevent the
|
|
// touchstart event in that case.
|
|
if (
|
|
touchXPosition - touchXRadius < 10 ||
|
|
touchXPosition + touchXRadius > window.innerWidth - 10
|
|
)
|
|
event.preventDefault()
|
|
}
|
|
|
|
sliderContainerRef.current!.addEventListener(
|
|
'touchstart',
|
|
preventNavigation
|
|
)
|
|
|
|
return () => {
|
|
if (sliderContainerRef.current) {
|
|
sliderContainerRef.current!.removeEventListener(
|
|
'touchstart',
|
|
preventNavigation
|
|
)
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
const onPrev = React.useCallback(() => slider.prev(), [slider])
|
|
const onNext = React.useCallback(() => slider.next(), [slider])
|
|
|
|
return (
|
|
<div className={cn(s.root, className)} ref={sliderContainerRef}>
|
|
<div
|
|
ref={ref}
|
|
className={cn(s.slider, { [s.show]: isMounted }, 'keen-slider')}
|
|
>
|
|
{slider && <ProductSliderControl onPrev={onPrev} onNext={onNext} />}
|
|
{Children.map(children, (child) => {
|
|
// Add the keen-slider__slide className to children
|
|
if (isValidElement(child)) {
|
|
return {
|
|
...child,
|
|
props: {
|
|
...child.props,
|
|
className: `${
|
|
child.props.className ? `${child.props.className} ` : ''
|
|
}keen-slider__slide`,
|
|
},
|
|
}
|
|
}
|
|
return child
|
|
})}
|
|
</div>
|
|
|
|
<a.div className={s.album} ref={thumbsContainerRef}>
|
|
{slider &&
|
|
Children.map(children, (child, idx) => {
|
|
if (isValidElement(child)) {
|
|
return {
|
|
...child,
|
|
props: {
|
|
...child.props,
|
|
className: cn(child.props.className, s.thumb, {
|
|
[s.selected]: currentSlide === idx,
|
|
}),
|
|
id: `thumb-${idx}`,
|
|
onClick: () => {
|
|
slider.moveToSlideRelative(idx)
|
|
},
|
|
},
|
|
}
|
|
}
|
|
return child
|
|
})}
|
|
</a.div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ProductSlider
|