import React, { useContext, useMemo } from 'react';
import {
Animated,
Dimensions,
PanResponder,
StyleSheet,
View,
type PanResponderCallbacks,
} from 'react-native';
import Navigation from './components/Navigation';
import Slide from './components/Slide';
import SliderProvider, { SliderContext } from './components/SliderProvider';
import { type SliderIntroProps } from './types/SliderIntro.types';
import type { SliderIntroItemProps } from './types/SliderIntroItem.types';
const styles = StyleSheet.create({
wrapper: {
flex: 1,
flexDirection: 'row',
},
});
const deviceMaxWidth = Dimensions.get('window').width;
const Slider = ({ children }: { children: React.ReactNode }) => {
const {
data,
numberOfSlides,
dotWidth = 12,
slidesMaxWidth,
limitToSlide,
dotMaxPossibleWidth,
slide,
goToNewSlide,
animations,
} = useContext(SliderContext);
const { active, slideToValue, dotWidthToValue } = slide;
const { _moveSlideTranslateX, _slideDotScaleX, _slideDotTranslateX } =
animations;
const panResponderConfig: PanResponderCallbacks = useMemo(() => {
const _onGestureEvent = (translationX: number) => {
const newValue = translationX + slideToValue;
const newDotWidthRawValue =
dotMaxPossibleWidth / (deviceMaxWidth / translationX);
const newDotWidthValue =
translationX < 0 ? -1 * newDotWidthRawValue : newDotWidthRawValue;
if (newValue > 0) {
_slideDotTranslateX.setValue(dotWidthToValue);
_moveSlideTranslateX.setValue(0);
_slideDotScaleX.setValue(1);
return;
}
if (newValue < -slidesMaxWidth) {
_slideDotTranslateX.setValue(dotWidthToValue);
_moveSlideTranslateX.setValue(slideToValue);
_slideDotScaleX.setValue(1);
return;
}
_moveSlideTranslateX.setValue(newValue);
if (newDotWidthValue <= dotWidth) {
_slideDotTranslateX.setValue(dotWidthToValue);
_slideDotScaleX.setValue(1);
return;
}
const newDotWidth =
newDotWidthValue / dotWidth < 3 ? newDotWidthValue / dotWidth : 3;
if (translationX < 0) {
_slideDotTranslateX.setValue(
dotWidthToValue + newDotWidthValue - dotWidth
);
_slideDotScaleX.setValue(newDotWidth);
return;
}
_slideDotTranslateX.setValue(
dotWidthToValue - newDotWidthValue + dotWidth
);
_slideDotScaleX.setValue(newDotWidth);
};
const _onHandlerStateChange = (translationX: number) => {
const newValue = translationX + slideToValue;
if (!(newValue <= 0 && newValue >= -slidesMaxWidth)) {
return;
}
let absoluteTranslation = 0;
if (translationX < 0) {
absoluteTranslation = translationX * -1;
if (limitToSlide && absoluteTranslation > limitToSlide) {
goToNewSlide(active + 1);
return;
}
goToNewSlide(active);
return;
}
absoluteTranslation = translationX;
if (limitToSlide && absoluteTranslation > limitToSlide) {
goToNewSlide(active - 1);
return;
}
goToNewSlide(active);
};
return {
onStartShouldSetPanResponder: () => false,
onMoveShouldSetPanResponder: (_, gestureState) => {
return gestureState.dx !== 0 && gestureState.dy !== 0;
},
onMoveShouldSetPanResponderCapture: (_, gestureState) => {
return gestureState.dx !== 0 && gestureState.dy !== 0;
},
onStartShouldSetPanResponderCapture: () => false,
onPanResponderMove: (_, gesture) => {
_onGestureEvent(gesture.dx);
},
onPanResponderRelease: (_, gesture) => {
_onHandlerStateChange(gesture.dx);
},
};
}, [
_slideDotTranslateX,
_slideDotScaleX,
_moveSlideTranslateX,
active,
dotWidthToValue,
dotMaxPossibleWidth,
dotWidth,
goToNewSlide,
limitToSlide,
slideToValue,
slidesMaxWidth,
]);
const panResponder = PanResponder.create(panResponderConfig);
return (
{children ? (
<>{children}>
) : (
<>
{data?.map((item: SliderIntroItemProps, index) => (
))}
>
)}
);
};
const SliderIntro = (props: Partial) => (
);
export default SliderIntro;
export { type SliderIntroItemProps, type SliderIntroProps };