diff --git a/.changeset/rare-frogs-swim.md b/.changeset/rare-frogs-swim.md new file mode 100644 index 00000000..87d9ad77 --- /dev/null +++ b/.changeset/rare-frogs-swim.md @@ -0,0 +1,5 @@ +--- +'nuka-carousel': patch +--- + +fix carousel missing last page if it is less than half of the container width in scrollDistance screen diff --git a/packages/nuka/src/hooks/use-measurement.test.tsx b/packages/nuka/src/hooks/use-measurement.test.tsx index 44290577..354b8861 100644 --- a/packages/nuka/src/hooks/use-measurement.test.tsx +++ b/packages/nuka/src/hooks/use-measurement.test.tsx @@ -121,7 +121,7 @@ describe('useMeasurement', () => { const { totalPages, scrollOffset } = result.current; expect(totalPages).toBe(2); - expect(scrollOffset).toEqual([0, 500]); + expect(scrollOffset).toEqual([0, 400]); }); it('should return measurements for screen with fractional pixels', () => { @@ -150,8 +150,36 @@ describe('useMeasurement', () => { const { totalPages, scrollOffset } = result.current; - expect(totalPages).toBe(3); - expect(scrollOffset).toEqual([0, 573, 1146]); + expect(totalPages).toBe(4); + // 573 * 0, 573 * 1, 573 * 2, 573 * 3 + (1720 - 573 * 3) + expect(scrollOffset).toEqual([0, 573, 1146, 1147]); + }); + + it('should return measurements for screen with less than half offset', () => { + const element = { + current: { + // this test covers that even when the leftover width is less than + // half of the screen width, it should still be scrollable so that user can see + // the small overflow + scrollWidth: 600, + offsetWidth: 500, + querySelector: () => ({ + children: [{ offsetWidth: 200 }, { offsetWidth: 400 }], + }), + }, + } as any; + + const { result } = renderHook(() => + useMeasurement({ + element, + scrollDistance: 'screen', + }), + ); + + const { totalPages, scrollOffset } = result.current; + + expect(totalPages).toBe(2); + expect(scrollOffset).toEqual([0, 100]); }); it('should return measurements for slide distance', () => { diff --git a/packages/nuka/src/hooks/use-measurement.tsx b/packages/nuka/src/hooks/use-measurement.tsx index 6b3b7ef2..647035ba 100644 --- a/packages/nuka/src/hooks/use-measurement.tsx +++ b/packages/nuka/src/hooks/use-measurement.tsx @@ -29,10 +29,17 @@ export function useMeasurement({ element, scrollDistance }: MeasurementProps) { switch (scrollDistance) { case 'screen': { - const pageCount = Math.round(scrollWidth / visibleWidth); + const pageCount = Math.ceil(scrollWidth / visibleWidth); + // For every page of the visibleWidth, we should scroll by the amount of the width + const fullScrollOffsets = arraySeq(pageCount - 1, visibleWidth); + // For the last page, we should only scroll by the leftover amount + const leftoverLastPage = scrollWidth % visibleWidth; setTotalPages(pageCount); - setScrollOffset(arraySeq(pageCount, visibleWidth)); + setScrollOffset([ + ...fullScrollOffsets, + fullScrollOffsets[fullScrollOffsets.length - 1] + leftoverLastPage, + ]); break; } case 'slide': {