Skip to content

Commit

Permalink
feat: change modal animation library
Browse files Browse the repository at this point in the history
  • Loading branch information
BartoszGrajdek committed Nov 6, 2024
1 parent bbc0919 commit fb2f774
Show file tree
Hide file tree
Showing 8 changed files with 968 additions and 0 deletions.
75 changes: 75 additions & 0 deletions src/components/Modal/ReactNativeModal/Backdrop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type {ReactNode} from 'react';
import React, {useEffect} from 'react';
import ReAnimated, {Easing, ReduceMotion, useAnimatedStyle, useSharedValue, withDelay, withTiming} from 'react-native-reanimated';
import {PressableWithFeedback} from '@components/Pressable';
import styles from './modal.style';

type BackdropProps = {
getDeviceWidth: () => number;
getDeviceHeight: () => number;
backdropColor: string;
hasBackdrop: boolean;
customBackdrop?: ReactNode;
isVisible: boolean;
isTransitioning: boolean;
backdropOpacity: number;
onBackdropPress: () => void;
};

function Backdrop({getDeviceWidth, backdropColor, getDeviceHeight, hasBackdrop, customBackdrop, isVisible, isTransitioning, backdropOpacity, onBackdropPress, ...props}: BackdropProps) {
const opacityValue = useSharedValue(0);

useEffect(() => {
if (!isTransitioning) {
return;
}
opacityValue.value = withDelay(0, withTiming(isVisible ? backdropOpacity : 0, {duration: 300, easing: Easing.inOut(Easing.ease), reduceMotion: ReduceMotion.Never}));
}, [isVisible, isTransitioning, backdropOpacity, opacityValue]);

const animatedStyle = useAnimatedStyle(() => {
return {
opacity: opacityValue.value,
};
});

if (!hasBackdrop) {
return null;
}

const hasCustomBackdrop = !!customBackdrop;

const backdropComputedStyle = [
{
width: getDeviceWidth(),
height: getDeviceHeight(),
backgroundColor: backdropColor,
},
];

const BDComponent = (
<ReAnimated.View
style={[styles.backdrop, backdropComputedStyle, animatedStyle]}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
>
{hasCustomBackdrop && customBackdrop}
</ReAnimated.View>
);

if (!hasCustomBackdrop) {
return (
<PressableWithFeedback
accessible
accessibilityLabel="test"
onPress={onBackdropPress}
pressDimmingValue={1}
>
{BDComponent}
</PressableWithFeedback>
);
}

return BDComponent;
}

export default Backdrop;
69 changes: 69 additions & 0 deletions src/components/Modal/ReactNativeModal/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, {useEffect, useState} from 'react';
import type {LayoutChangeEvent} from 'react-native';
import Animated, {Easing, SlideInDown, useAnimatedRef, useAnimatedStyle, useSharedValue, withDelay, withTiming} from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';

type ContainerProps = Partial<ModalProps> & {
isVisible: boolean;
isContainerOpen: boolean;
isTransitioning: boolean;
isHeightCalculated: boolean;
toggleCalculatedHeight: (value: boolean) => void;
deviceHeight?: number | undefined | null;
style?: any;
onLayout?: (event: LayoutChangeEvent) => void;
setMeasuredHeight: (value: number) => void;
};

function Container({isVisible, isContainerOpen, isTransitioning, isHeightCalculated, toggleCalculatedHeight, style, onLayout, setMeasuredHeight, testName, ...props}: ContainerProps) {
const styles = useThemeStyles();
const animatedRef = useAnimatedRef();
const [measuredHeight, setMH] = useState<number>(0);

const translateY = useSharedValue(500);

useEffect(() => {
if (!isTransitioning) {
return;
}
// console.log(testName, ' Container: isVisible & translateY', isVisible, isVisible ? 0 : 500);
// eslint-disable-next-line react-compiler/react-compiler
translateY.value = withDelay(0, withTiming(isVisible ? 0 : 500, {duration: 300, easing: Easing.inOut(Easing.ease)}));
setMH(0);
}, [isVisible, isTransitioning]);

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [{translateY: translateY.value}],
opacity: !isHeightCalculated || (isVisible !== isContainerOpen && !isTransitioning) ? 0 : 1,
};
});

console.log('props: ', Object.keys(props).join('-'));
return (
<Animated.View
ref={animatedRef}
style={[style, animatedStyles]}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
{...props.panHandlers}
>
<Animated.View
// TODO: check this 100%
style={{width: '100%'}}
onLayout={(event) => {
if (!measuredHeight && event.nativeEvent.layout.height && measuredHeight !== event.nativeEvent.layout.height) {
// translateY.value = 500;
setMH(event.nativeEvent.layout.height);
setMeasuredHeight(event.nativeEvent.layout.height);
toggleCalculatedHeight(true);
}
}}
>
{props.children}
</Animated.View>
</Animated.View>
);
}

export default Container;
Loading

0 comments on commit fb2f774

Please sign in to comment.