mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-20 09:01:19 +00:00
83 lines
1.8 KiB
TypeScript
83 lines
1.8 KiB
TypeScript
|
|
import type { PropsWithChildren, ReactElement } from "react"
|
||
|
|
|
||
|
|
import { StyleSheet } from "react-native"
|
||
|
|
import Animated, {
|
||
|
|
interpolate,
|
||
|
|
useAnimatedRef,
|
||
|
|
useAnimatedStyle,
|
||
|
|
useScrollOffset,
|
||
|
|
} from "react-native-reanimated"
|
||
|
|
|
||
|
|
import { ThemedView } from "@/components/themed-view"
|
||
|
|
import { useColorScheme } from "@/hooks/use-color-scheme"
|
||
|
|
import { useThemeColor } from "@/hooks/use-theme-color"
|
||
|
|
|
||
|
|
const HEADER_HEIGHT = 250
|
||
|
|
|
||
|
|
type Props = PropsWithChildren<{
|
||
|
|
headerImage: ReactElement
|
||
|
|
headerBackgroundColor: { dark: string; light: string }
|
||
|
|
}>
|
||
|
|
|
||
|
|
export default function ParallaxScrollView({
|
||
|
|
children,
|
||
|
|
headerImage,
|
||
|
|
headerBackgroundColor,
|
||
|
|
}: Props) {
|
||
|
|
const backgroundColor = useThemeColor({}, "background")
|
||
|
|
const colorScheme = useColorScheme() ?? "light"
|
||
|
|
const scrollRef = useAnimatedRef<Animated.ScrollView>()
|
||
|
|
const scrollOffset = useScrollOffset(scrollRef)
|
||
|
|
const headerAnimatedStyle = useAnimatedStyle(() => {
|
||
|
|
return {
|
||
|
|
transform: [
|
||
|
|
{
|
||
|
|
translateY: interpolate(
|
||
|
|
scrollOffset.value,
|
||
|
|
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
|
||
|
|
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75],
|
||
|
|
),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Animated.ScrollView
|
||
|
|
ref={scrollRef}
|
||
|
|
style={{ backgroundColor, flex: 1 }}
|
||
|
|
scrollEventThrottle={16}
|
||
|
|
>
|
||
|
|
<Animated.View
|
||
|
|
style={[
|
||
|
|
styles.header,
|
||
|
|
{ backgroundColor: headerBackgroundColor[colorScheme] },
|
||
|
|
headerAnimatedStyle,
|
||
|
|
]}
|
||
|
|
>
|
||
|
|
{headerImage}
|
||
|
|
</Animated.View>
|
||
|
|
<ThemedView style={styles.content}>{children}</ThemedView>
|
||
|
|
</Animated.ScrollView>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
const styles = StyleSheet.create({
|
||
|
|
container: {
|
||
|
|
flex: 1,
|
||
|
|
},
|
||
|
|
header: {
|
||
|
|
height: HEADER_HEIGHT,
|
||
|
|
overflow: "hidden",
|
||
|
|
},
|
||
|
|
content: {
|
||
|
|
flex: 1,
|
||
|
|
padding: 32,
|
||
|
|
gap: 16,
|
||
|
|
overflow: "hidden",
|
||
|
|
},
|
||
|
|
})
|