Skip to content

Commit

Permalink
crear componente carousel
Browse files Browse the repository at this point in the history
  • Loading branch information
damian committed Oct 23, 2023
1 parent 671197e commit fa92027
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 161 deletions.
66 changes: 66 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"lint": "eslint .",
"prepare": "husky install",
"validate:code": "npm run lint -- --fix && tsc --noEmit && npm t",
"test:commit": "jest --colors --bail --findRelatedTests --detectOpenHandles",
"test:coverage": "tsc --noEmit && jest --collectCoverage",
"test:commit": "jest --colors --bail --findRelatedTests",
"test:coverage": "tsc --noEmit && jest --collectCoverage --detectOpenHandles",
"build": "rm -rf dist && tsc",
"storybook": "react-native-storybook-server",
"storybook-watcher": "sb-rn-watcher --config-path .ondevice",
Expand Down Expand Up @@ -60,6 +60,7 @@
"@storybook/react": "^6.5.4",
"@storybook/react-native": "^6.5.4",
"@storybook/react-native-server": "^6.5.4",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/react-native": "^7.2.0",
"@types/jest": "^25.2.3",
"@types/react": "^17.0.2",
Expand Down
53 changes: 7 additions & 46 deletions src/components/Carousel/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {ScrollView} from 'react-native';
import Text from '../Text';
import Carousel from './';

const validPages = [<Text>Page</Text>, <Text>Page</Text>, <Text>Page</Text>];
const validPages = [<Text>Page1</Text>, <Text>Page2</Text>, <Text>Page3</Text>];
const validProps = {
pages: validPages,
isLoop: true,
Expand Down Expand Up @@ -56,7 +56,7 @@ describe('Carousel component', () => {
const CarouselComp = create(
<Carousel
pages={validProps.pages}
callback={(params) => {
buttonsCallback={(params) => {
params.goPrev();
params.goPrev();
}}
Expand All @@ -74,7 +74,7 @@ describe('Carousel component', () => {
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
callback={(params) => {
buttonsCallback={(params) => {
params.goPrev();
params.goPrev();
}}
Expand All @@ -92,7 +92,7 @@ describe('Carousel component', () => {
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
callback={(params) => {
buttonsCallback={(params) => {
params.goPrev();
params.goPrev();
}}
Expand All @@ -111,7 +111,7 @@ describe('Carousel component', () => {
const {root} = create(
<Carousel
pages={validProps.pages}
callback={(params) => {
buttonsCallback={(params) => {
params.goNext();
}}
/>
Expand All @@ -128,7 +128,7 @@ describe('Carousel component', () => {
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
callback={(params) => {
buttonsCallback={(params) => {
params.goNext();
}}
/>
Expand All @@ -145,51 +145,12 @@ describe('Carousel component', () => {
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
callback={(params) => {
buttonsCallback={(params) => {
params.goNext();
}}
/>
);
expect(root).toBeTruthy();
});
});

describe('autoplay when', () => {
it('is autoplay', () => {
spyUseState.mockReturnValueOnce([0, setActivePage]);
spyUseRef.mockReturnValueOnce({current: {scrollTo}});
spyUseEffect.mockImplementation((f) => f());

const {root} = create(
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
autoplay={validProps.autoplay}
autoPlayReverse={false}
/>
);
// jest.advanceTimersByTime(4000);

expect(root).toBeTruthy();
});

it('is autoplay in reverse', () => {
spyUseState.mockReturnValueOnce([0, setActivePage]);
spyUseRef.mockReturnValueOnce({current: {scrollTo}});
spyUseEffect.mockImplementation((f) => f());

const {root} = create(
<Carousel
pages={validProps.pages}
isLoop={validProps.isLoop}
autoplay={false}
autoPlayReverse={validProps.autoplay}
customWidth={200}
/>
);
// jest.advanceTimersByTime(4000);

expect(root).toBeTruthy();
});
});
});
125 changes: 18 additions & 107 deletions src/components/Carousel/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import React, {FC, useCallback, useEffect, useRef, useState} from 'react';
import {
Dimensions,
NativeScrollEvent,
NativeSyntheticEvent,
ScrollView,
StyleSheet,
View,
} from 'react-native';
import React, {FC} from 'react';
import {ScrollView, StyleSheet, View} from 'react-native';
import useCarouselControls from './utils';

interface CarouselProps {
export interface CarouselProps {
pages: React.ReactNode[];
isLoop?: boolean;
autoplay?: boolean;
autoPlayReverse?: boolean;
intervalTime?: number;
customWidth?: number;
callback?: (params: {
activePage: number;
pagesLength: number;
goPrev: () => void;
goNext: () => void;
}) => void | null;
buttonsCallback?: (params: {goPrev: () => void; goNext: () => void}) => void | null;
pagesCallback?: (params: {activePage: number; pagesLength: number}) => void | null;
}

const Carousel: FC<CarouselProps> = ({
Expand All @@ -30,100 +20,21 @@ const Carousel: FC<CarouselProps> = ({
autoPlayReverse = false,
intervalTime = 4000,
customWidth,
callback,
buttonsCallback,
pagesCallback,
...props
}) => {
const [activePage, setActivePage] = useState(0);
const slider = useRef<ScrollView | null>(null);

const {width: screenWidth} = Dimensions.get('screen');
const width = customWidth ?? screenWidth;

const onPageChange = ({nativeEvent}: NativeSyntheticEvent<NativeScrollEvent>) => {
const slide =
Math.floor(
(nativeEvent.contentOffset?.x - nativeEvent.layoutMeasurement?.width / 2) /
nativeEvent.layoutMeasurement?.width
) + 1;
/* istanbul ignore next */
if (slide !== activePage && slide < (pages.length || 0)) {
setActivePage(slide);
}
const carouselParams = {
pages,
isLoop,
autoplay,
autoPlayReverse,
intervalTime,
customWidth,
buttonsCallback,
pagesCallback,
};

const goNext = useCallback(() => {
if (isLoop && activePage === pages.length - 1) {
slider.current?.scrollTo({
x: (activePage - pages.length - 1) * width,
animated: true,
});
} else {
slider.current?.scrollTo({
x: (activePage + 1) * width,
animated: true,
});
}
if (!isLoop && activePage !== pages.length - 1) {
slider.current?.scrollTo({
x: (activePage + 1) * width,
animated: true,
});
}
}, [activePage, isLoop, width, pages.length]);

const goPrev = useCallback(() => {
if (isLoop && activePage === 0) {
slider.current?.scrollTo({
x: (activePage + pages.length - 1) * width,
animated: true,
});
} else {
slider.current?.scrollTo({
x: (activePage - 1) * width,
animated: true,
});
}
if (!isLoop) {
slider.current?.scrollTo({
x: (activePage - 1) * width,
animated: true,
});
}
}, [activePage, isLoop, width, pages.length]);

const initAutoPlay = useCallback(() => {
/* istanbul ignore next */
return setInterval(() => {
if (autoplay && !autoPlayReverse) {
goNext();
}
if (!autoplay && autoPlayReverse) {
goPrev();
}
}, intervalTime);
}, [autoplay, autoPlayReverse, intervalTime, goPrev, goNext]);

const setCallback = useCallback(() => {
callback &&
callback({
activePage,
pagesLength: pages.length,
goPrev,
goNext,
});
}, [pages, activePage, goPrev, goNext, callback]);

useEffect(() => {
const intervalId = initAutoPlay();
/* istanbul ignore next */
return () => clearInterval(intervalId);
}, [initAutoPlay]);

useEffect(() => {
if (callback) {
setCallback();
}
}, [callback, setCallback]);
const {slider, width, onPageChange} = useCarouselControls(carouselParams);

const styles = StyleSheet.create({
page: {
Expand Down

0 comments on commit fa92027

Please sign in to comment.