-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
53 changed files
with
21,624 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,3 +76,6 @@ android/keystores/debug.keystore | |
|
||
# generated by bob | ||
lib/ | ||
|
||
# env | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import React, { useEffect, useRef } from 'react'; | ||
import { View, Text, StyleSheet, Animated, Easing, Modal } from 'react-native'; | ||
import { hostColors } from '../../styles/colors'; | ||
|
||
interface ModalLoaderProps { | ||
visible: boolean; | ||
text?: string; | ||
} | ||
|
||
export function ModalLoader({ visible, text }: ModalLoaderProps) { | ||
const rotation = useRef(new Animated.Value(0)).current; | ||
const dot1 = useRef(new Animated.Value(0)).current; | ||
const dot2 = useRef(new Animated.Value(0)).current; | ||
const dot3 = useRef(new Animated.Value(0)).current; | ||
|
||
useEffect(() => { | ||
const rotate = Animated.loop( | ||
Animated.timing(rotation, { | ||
toValue: 1, | ||
duration: 1000, | ||
easing: Easing.linear, | ||
useNativeDriver: true, | ||
}) | ||
); | ||
|
||
const animateDots = (dot: Animated.Value, delay: number) => { | ||
return Animated.loop( | ||
Animated.sequence([ | ||
Animated.timing(dot, { | ||
toValue: -10, | ||
duration: 300, | ||
delay, | ||
easing: Easing.ease, | ||
useNativeDriver: true, | ||
}), | ||
Animated.timing(dot, { | ||
toValue: 0, | ||
duration: 300, | ||
easing: Easing.ease, | ||
useNativeDriver: true, | ||
}), | ||
]) | ||
); | ||
}; | ||
|
||
let animationDot1 = animateDots(dot1, 0); | ||
let animationDot2 = animateDots(dot2, 150); | ||
let animationDot3 = animateDots(dot3, 300); | ||
|
||
if (visible) { | ||
rotate.start(); | ||
animationDot1.start(); | ||
animationDot2.start(); | ||
animationDot3.start(); | ||
} else { | ||
rotation.setValue(0); | ||
dot1.setValue(0); | ||
dot2.setValue(0); | ||
dot3.setValue(0); | ||
rotate.stop(); | ||
animationDot1.stop(); | ||
animationDot2.stop(); | ||
animationDot3.stop(); | ||
} | ||
|
||
// Cleanup function to stop animations | ||
return () => { | ||
rotate.stop(); | ||
animationDot1.stop(); | ||
animationDot2.stop(); | ||
animationDot3.stop(); | ||
}; | ||
}, [visible, rotation, dot1, dot2, dot3]); | ||
|
||
const rotateInterpolate = rotation.interpolate({ | ||
inputRange: [0, 1], | ||
outputRange: ['0deg', '360deg'], | ||
}); | ||
|
||
const animatedStyle = { | ||
transform: [{ rotate: rotateInterpolate }], | ||
}; | ||
|
||
const dotStyle = (dot: Animated.Value) => ({ | ||
transform: [{ translateY: dot }], | ||
}); | ||
|
||
return ( | ||
<Modal visible={visible} transparent={false} style={styles.container}> | ||
<View style={styles.container}> | ||
<Animated.View style={[styles.loader, animatedStyle]}> | ||
<View style={styles.circle} /> | ||
</Animated.View> | ||
<View style={styles.loadingContainer}> | ||
<Text style={styles.loadingText}>{text || 'Loading '}</Text> | ||
<Animated.Text style={[styles.dot, dotStyle(dot1)]}>.</Animated.Text> | ||
<Animated.Text style={[styles.dot, dotStyle(dot2)]}>.</Animated.Text> | ||
<Animated.Text style={[styles.dot, dotStyle(dot3)]}>.</Animated.Text> | ||
</View> | ||
</View> | ||
</Modal> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
backgroundColor: hostColors.backgroundColor, | ||
}, | ||
loader: { | ||
width: 100, | ||
height: 100, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
}, | ||
circle: { | ||
width: 100, | ||
height: 100, | ||
borderWidth: 10, | ||
borderColor: hostColors.primaryColor, | ||
borderRadius: 50, | ||
borderTopColor: 'transparent', | ||
}, | ||
loadingContainer: { | ||
flexDirection: 'row', | ||
marginTop: 20, | ||
}, | ||
loadingText: { | ||
fontSize: 24, | ||
color: hostColors.primaryColor, | ||
}, | ||
dot: { | ||
fontSize: 24, | ||
color: hostColors.primaryColor, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React, { useRef, useEffect } from 'react'; | ||
import { type ReactNode } from 'react'; | ||
import { Animated } from 'react-native'; | ||
import { type StyleProp, type ViewStyle } from 'react-native'; | ||
|
||
interface FadeWrapperProps { | ||
children: ReactNode; | ||
style?: StyleProp<ViewStyle>; | ||
} | ||
|
||
export const FadeWrapper: React.FC<FadeWrapperProps> = ({ | ||
children, | ||
style, | ||
}) => { | ||
const fadeAnim = useRef(new Animated.Value(0)).current; | ||
|
||
useEffect(() => { | ||
Animated.timing(fadeAnim, { | ||
toValue: 1, | ||
duration: 500, | ||
useNativeDriver: true, | ||
}).start(); | ||
|
||
return () => { | ||
Animated.timing(fadeAnim, { | ||
toValue: 0, | ||
duration: 500, | ||
useNativeDriver: true, | ||
}).start(); | ||
}; | ||
}, [fadeAnim]); | ||
|
||
return ( | ||
<Animated.View style={[style, { opacity: fadeAnim }]}> | ||
{children} | ||
</Animated.View> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import React, { useEffect, useRef, useState } from 'react'; | ||
import { | ||
Animated, | ||
Dimensions, | ||
Modal, | ||
StyleSheet, | ||
TouchableOpacity, | ||
View, | ||
} from 'react-native'; | ||
import { hostColors } from '../../styles/colors'; | ||
|
||
const windowHeight = Dimensions.get('window').height; | ||
|
||
interface BottomSheetProps { | ||
isVisible: boolean; | ||
setModalVisible: (isVisible: boolean) => void; | ||
children: React.ReactNode; | ||
} | ||
|
||
export const BottomSheet: React.FC<BottomSheetProps> = ({ | ||
isVisible, | ||
setModalVisible, | ||
children, | ||
}) => { | ||
const [showModal, setShowModal] = useState(isVisible); | ||
const slideAnim = useRef(new Animated.Value(windowHeight)).current; | ||
|
||
useEffect(() => { | ||
if (isVisible) { | ||
setShowModal(true); | ||
Animated.timing(slideAnim, { | ||
toValue: 0, | ||
duration: 300, | ||
useNativeDriver: true, | ||
}).start(); | ||
} else { | ||
Animated.timing(slideAnim, { | ||
toValue: windowHeight, | ||
duration: 300, | ||
useNativeDriver: true, | ||
}).start(() => { | ||
setShowModal(false); | ||
}); | ||
} | ||
}, [isVisible, slideAnim]); | ||
|
||
const handleClose = () => { | ||
Animated.timing(slideAnim, { | ||
toValue: windowHeight, | ||
duration: 300, | ||
useNativeDriver: true, | ||
}).start(() => { | ||
setShowModal(false); | ||
setModalVisible(false); | ||
}); | ||
}; | ||
|
||
return ( | ||
<Modal visible={showModal} onRequestClose={handleClose} transparent> | ||
<View style={styles.container}> | ||
<TouchableOpacity | ||
style={styles.overlay} | ||
activeOpacity={1} | ||
onPress={handleClose} | ||
/> | ||
<Animated.View | ||
style={[ | ||
styles.contentContainer, | ||
{ transform: [{ translateY: slideAnim }] }, | ||
]} | ||
> | ||
{children} | ||
</Animated.View> | ||
</View> | ||
</Modal> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
justifyContent: 'flex-end', | ||
backgroundColor: 'rgba(0,0,0,0.5)', | ||
}, | ||
overlay: { | ||
flex: 1, | ||
}, | ||
contentContainer: { | ||
backgroundColor: hostColors.white, | ||
paddingTop: 5, | ||
maxHeight: windowHeight * 0.75, | ||
minHeight: windowHeight * 0.25, | ||
borderTopLeftRadius: 20, | ||
borderTopRightRadius: 20, | ||
paddingBottom: 50, | ||
}, | ||
}); |
Oops, something went wrong.