Skip to content

Commit

Permalink
Merge pull request #10 from mrpmohiburrahman/mrp/beforeAfter
Browse files Browse the repository at this point in the history
add slider support
  • Loading branch information
Omerdogan3 authored Oct 4, 2022
2 parents 922c60c + 8f3faa7 commit 9226aa6
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 311 deletions.
60 changes: 60 additions & 0 deletions src/compare-slider/components/CompareSlider/CompareSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { View } from 'react-native';

import { Slider } from '../Slider';
import { ICompareSlider } from '../../types';

import { styles } from './styles';
import Animated, { useAnimatedStyle, useDerivedValue, useSharedValue } from 'react-native-reanimated';

export const CompareSlider: React.FC<ICompareSlider> = props => {
const { before, after, containerSize, sliderSize, SliderComponent, sliderStyles, showSeparationLine } = props;
const { width: containerWidth, height: containerHeight } = containerSize;

const translateX = useSharedValue(0);
const boxWidth = useDerivedValue(() => translateX.value + containerWidth / 2, [translateX]);

const updateTranslateX = (value: any) => {
'worklet';
translateX.value = value;
};
const animatedStyle = {
before: useAnimatedStyle(() => ({
width: boxWidth.value,
})),
after: useAnimatedStyle(() => ({
left: boxWidth.value,
})),
};
return (
<View
style={[
{
width: containerWidth,
height: containerHeight,
overflow: 'hidden',
},
]}>
<View
style={{
position: 'absolute',
width: containerWidth,
height: containerHeight,
}}>
<Animated.View style={[styles.item, styles.itemBefore, animatedStyle.before]}>{before}</Animated.View>
<Animated.View style={[styles.item, styles.itemAfter, animatedStyle.after]}>
<Animated.View style={[styles.itemAfterChild, { width: containerWidth }]}>{after}</Animated.View>
</Animated.View>
</View>
<Slider
translateX={translateX}
updateTranslateX={updateTranslateX}
sliderSize={sliderSize}
containerSize={containerSize}
sliderStyles={sliderStyles}
SliderComponent={SliderComponent}
showSeparationLine={showSeparationLine}
/>
</View>
);
};
3 changes: 3 additions & 0 deletions src/compare-slider/components/CompareSlider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { CompareSlider } from './CompareSlider';

export { CompareSlider };
21 changes: 21 additions & 0 deletions src/compare-slider/components/CompareSlider/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
item: {
position: 'absolute',
top: 0,
bottom: 0,
overflow: 'hidden',
},
itemBefore: {
left: 0,
},
itemAfter: {
right: 0,
},
itemAfterChild: {
position: 'absolute',
right: 0,
top: 0,
},
});
62 changes: 62 additions & 0 deletions src/compare-slider/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { View } from 'react-native';
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';

import { DEFAULT_SLIDER_SIZE } from '../../utils/constants';
import { IDefaultSliderProps, ISliderProps } from '../../types';

import { styles } from './styles';
import Animated, { useAnimatedGestureHandler, useAnimatedStyle, Value } from 'react-native-reanimated';
import { clamp } from 'react-native-redash';

const initialAnimatedValue = new Value(0);

const DefaultSlider: React.FC<IDefaultSliderProps> = ({ sliderSize = DEFAULT_SLIDER_SIZE, sliderStyles }) => {
return (
<View style={[styles.slider, sliderStyles, sliderSize]}>
<View style={[styles.sliderArrow, styles.sliderArrowRight]} />
<View style={[styles.sliderArrow, styles.sliderArrowLeft]} />
</View>
);
};

export const Slider: React.FC<ISliderProps> = props => {
const {
containerSize: { height: containerHeight, width },
translateX = initialAnimatedValue,
updateTranslateX,
sliderSize = DEFAULT_SLIDER_SIZE,
sliderStyles,
showSeparationLine = true,
separationLineStyles,
SliderComponent = <DefaultSlider sliderSize={sliderSize} sliderStyles={sliderStyles} />,
} = props;

const offsetFromEdges = 30;
const boundX = width / 2 - offsetFromEdges;

const onGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent, { offsetX: number }>({
onStart: (_event, ctx) => {
ctx.offsetX = translateX.value;
},
onActive: (event, ctx) => {
translateX.value = clamp(ctx.offsetX + event.translationX, -boundX, boundX);
updateTranslateX(translateX.value);
},
onEnd: () => {},
});
const animatedStyle = useAnimatedStyle(() => {
return { transform: [{ translateX: translateX.value }] };
});

return (
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[sliderSize, styles.animatedView, animatedStyle]} pointerEvents="box-only">
{showSeparationLine && (
<Animated.View style={[styles.separationLine, { height: containerHeight }, separationLineStyles]} />
)}
{SliderComponent}
</Animated.View>
</PanGestureHandler>
);
};
5 changes: 5 additions & 0 deletions src/compare-slider/components/Slider/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Slider } from './Slider';

it('Run fake test', () => {
expect(Slider).not.toBe(null);
});
3 changes: 3 additions & 0 deletions src/compare-slider/components/Slider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Slider } from './Slider';

export { Slider };
41 changes: 41 additions & 0 deletions src/compare-slider/components/Slider/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { StyleSheet } from 'react-native';
import { SLIDER_ARROW_SIZE, SLIDER_SIZE } from '../../utils/constants';

export const styles = StyleSheet.create({
animatedView: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
},
slider: {
alignItems: 'center',
backgroundColor: '#f5f6fa',
borderRadius: SLIDER_SIZE / 2,
justifyContent: 'center',
},
sliderArrow: {
width: SLIDER_ARROW_SIZE,
height: SLIDER_ARROW_SIZE,
position: 'absolute',
borderTopWidth: SLIDER_ARROW_SIZE,
borderTopColor: 'transparent',
borderBottomWidth: SLIDER_ARROW_SIZE,
borderBottomColor: 'transparent',
},
sliderArrowRight: {
right: 8,
borderLeftWidth: SLIDER_ARROW_SIZE,
borderLeftColor: 'green',
},
sliderArrowLeft: {
left: 8,
borderRightWidth: SLIDER_ARROW_SIZE,
borderRightColor: 'green',
},
separationLine: {
backgroundColor: '#f5f6fa',
width: 5,
position: 'absolute',
},
});
3 changes: 3 additions & 0 deletions src/compare-slider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { CompareSlider } from './components/CompareSlider';

export { CompareSlider };
39 changes: 39 additions & 0 deletions src/compare-slider/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// All types for src/components/** goes here
// and some types can be inside component - not needed for external usage

import React from 'react';
import { ViewStyle } from 'react-native';

export interface ISize {
width: number;
height: number;
}

export interface IDefaultSliderProps {
sliderSize?: ISize;
sliderStyles?: ViewStyle;
}

export interface ISliderProps extends IDefaultSliderProps {
translateX: any;
updateTranslateX: any;
SliderComponent?: React.ReactNode;
containerSize: ISize;
showSeparationLine?: boolean;
separationLineStyles?: ViewStyle;
}

export interface ICompareSlider {
before: React.ReactNode;
after: React.ReactNode;
containerSize: ISize;

// Slider props
sliderSize?: ISize;
SliderComponent?: React.ReactNode;
sliderStyles?: ViewStyle;

// Separation line
showSeparationLine?: boolean;
separationLineStyles?: ViewStyle;
}
4 changes: 4 additions & 0 deletions src/compare-slider/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SLIDER_SIZE = 50;
export const DEFAULT_SLIDER_SIZE = { width: SLIDER_SIZE, height: SLIDER_SIZE };

export const SLIDER_ARROW_SIZE = 10;
Loading

0 comments on commit 9226aa6

Please sign in to comment.