@janiscommerce/ui-native
Version:
components library for Janis app
103 lines (102 loc) • 3.51 kB
JavaScript
import { useCallback, useEffect, useRef, useState } from 'react';
import { Dimensions } from 'react-native';
const useCarouselControls = ({ pages, isLoop, autoplay, autoPlayReverse, intervalTime, customWidth, buttonsCallback, pagesCallback, }) => {
const [activePage, setActivePage] = useState(0);
const slider = useRef(null);
const intervalId = useRef(null);
const { width: screenWidth } = Dimensions.get('screen');
const width = customWidth ?? screenWidth;
const pagesLength = pages.length - 1;
const onPageChange = ({ nativeEvent }) => {
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);
}
};
// action buttons
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,
});
}
}, [pages.length, activePage, isLoop, slider, width]);
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,
});
}
}, [pages.length, activePage, isLoop, slider, width]);
// auto play
const initAutoPlay = useCallback(() => setInterval(() => {
goNext();
}, intervalTime), [goNext, intervalTime]);
const initAutoPlayReverse = useCallback(() => setInterval(() => {
goPrev();
}, intervalTime), [goPrev, intervalTime]);
useEffect(() => {
if (autoplay && !autoPlayReverse) {
intervalId.current = initAutoPlay();
}
if (!autoplay && autoPlayReverse) {
intervalId.current = initAutoPlayReverse();
}
/* istanbul ignore next */
return () => {
if (intervalId.current) {
clearInterval(intervalId.current);
}
};
}, [autoplay, autoPlayReverse, initAutoPlay, initAutoPlayReverse]);
// callbacks
useEffect(() => {
if (buttonsCallback) {
buttonsCallback({ goPrev, goNext });
}
}, [buttonsCallback, goNext, goPrev]);
useEffect(() => {
if (pagesCallback) {
pagesCallback({ activePage, pagesLength });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activePage]);
return {
activePage,
slider,
intervalId,
width,
goPrev,
goNext,
onPageChange,
};
};
export default useCarouselControls;