diff --git a/src/hooks/useInterpolateInsideCarousel.ts b/src/hooks/useInterpolateInsideCarousel.ts index 5fe154b..b77f77d 100644 --- a/src/hooks/useInterpolateInsideCarousel.ts +++ b/src/hooks/useInterpolateInsideCarousel.ts @@ -8,9 +8,15 @@ export const useInterpolateInsideCarousel = (values: { valueAfter: number offset?: number }) => { - const { scrollValue } = useCarouselContext() + const { scrollValue, disableInfiniteScroll } = useCarouselContext() const { index, total } = useAutoCarouselSlideIndex() return useDerivedValue(() => { - return interpolateInsideCarousel(scrollValue.value, index, total, values) - }, [scrollValue, values]) + return interpolateInsideCarousel( + scrollValue.value, + index, + total, + values, + !disableInfiniteScroll, + ) + }, [scrollValue, values, disableInfiniteScroll]) } diff --git a/src/utils/__tests__/interpolateInsideCarousel.test.ts b/src/utils/__tests__/interpolateInsideCarousel.test.ts index 101c3c2..4209f40 100644 --- a/src/utils/__tests__/interpolateInsideCarousel.test.ts +++ b/src/utils/__tests__/interpolateInsideCarousel.test.ts @@ -300,4 +300,30 @@ describe('interpolateInsideCarousel', () => { }) expect(result).toBe(1) }) + + describe('without infinite scroll', () => { + // Three real slides and no clones, so the ends don't mirror each other. + const values = { valueBefore: 0, thisValue: 1, valueAfter: 0 } + + it('keeps the first slide at the side value while the second is current', () => { + expect(interpolateInsideCarousel(1, 0, 3, values, false)).toBe(0) + }) + + it('keeps the second slide at the side value while the last is current', () => { + expect(interpolateInsideCarousel(2, 1, 3, values, false)).toBe(0) + }) + + it('keeps the last slide at the side value while the second is current', () => { + expect(interpolateInsideCarousel(1, 2, 3, values, false)).toBe(0) + }) + + it('gives the current slide its own value', () => { + expect(interpolateInsideCarousel(0, 0, 3, values, false)).toBe(1) + expect(interpolateInsideCarousel(2, 2, 3, values, false)).toBe(1) + }) + + it('interpolates halfway between slides', () => { + expect(interpolateInsideCarousel(0.5, 0, 3, values, false)).toBe(0.5) + }) + }) }) diff --git a/src/utils/interpolateInsideCarousel.ts b/src/utils/interpolateInsideCarousel.ts index 51333d7..d64d09b 100644 --- a/src/utils/interpolateInsideCarousel.ts +++ b/src/utils/interpolateInsideCarousel.ts @@ -10,6 +10,9 @@ export const interpolateInsideCarousel = ( valueAfter: number offset?: number }, + // With infinite scroll the first and last slides are clones, so a slide also counts as current + // while its clone is. + isInfinite = true, ) => { 'worklet' const { valueBefore, thisValue, valueAfter, offset = 0 } = values @@ -27,6 +30,7 @@ export const interpolateInsideCarousel = ( } const getAdjustedIndex = (slideIndex: number) => { + if (!isInfinite) return slideIndex if (slideIndex === 0) return Math.max(totalLength - 2, 0) if (slideIndex === totalLength - 1) return 1 if (slideIndex === 1) return totalLength - 1